package com.cencat.driver.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cencat.driver.entity.Vehicle;
import com.cencat.driver.mapper.VehicleMapper;
import com.cencat.driver.service.VehicleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 车辆服务实现类
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VehicleServiceImpl extends ServiceImpl<VehicleMapper, Vehicle> implements VehicleService {

    private final VehicleMapper vehicleMapper;

    private static final String VEHICLE_CODE_PREFIX = "VEH";

    @Override
    public Vehicle getByLicensePlate(String licensePlate, Long tenantId) {
        return vehicleMapper.selectByLicensePlate(licensePlate, tenantId);
    }

    @Override
    public Vehicle getByVehicleCode(String vehicleCode, Long tenantId) {
        return vehicleMapper.selectByVehicleCode(vehicleCode, tenantId);
    }

    @Override
    public List<Vehicle> getByDriverId(Long driverId, Long tenantId) {
        return vehicleMapper.selectByDriverId(driverId, tenantId);
    }

    @Override
    public List<Vehicle> getByStatus(Integer status, Long tenantId) {
        return vehicleMapper.selectByStatus(status, tenantId);
    }

    @Override
    public List<Vehicle> getByVehicleType(Integer vehicleType, Long tenantId) {
        return vehicleMapper.selectByVehicleType(vehicleType, tenantId);
    }

    @Override
    public List<Vehicle> getAvailableVehicles(Long tenantId) {
        return vehicleMapper.selectAvailableVehicles(tenantId);
    }

    @Override
    public List<Vehicle> getUnassignedVehicles(Long tenantId) {
        return vehicleMapper.selectUnassignedVehicles(tenantId);
    }

    @Override
    public IPage<Vehicle> getPageList(Long current, Long size, String vehicleCode, String licensePlate,
                                    Long driverId, Integer status, Integer vehicleType, LocalDateTime startTime, LocalDateTime endTime, Long tenantId) {
        Page<Vehicle> page = new Page<>(current, size);
        return vehicleMapper.selectPageList(page, vehicleCode, licensePlate, driverId, status, vehicleType, startTime, endTime, tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createVehicle(Vehicle vehicle) {
        try {
            // 生成车辆编号
            vehicle.setVehicleCode(generateVehicleCode(vehicle.getTenantId()));
            
            // 设置默认值
            vehicle.setStatus(Vehicle.Status.ACTIVE.getValue());
            vehicle.setCreateTime(LocalDateTime.now());
            vehicle.setUpdateTime(LocalDateTime.now());
            
            int result = vehicleMapper.insert(vehicle);
            
            log.info("创建车辆成功: vehicleId={}, vehicleCode={}, licensePlate={}, tenantId={}", 
                    vehicle.getId(), vehicle.getVehicleCode(), vehicle.getLicensePlate(), vehicle.getTenantId());
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("创建车辆异常: licensePlate={}, tenantId={}", vehicle.getLicensePlate(), vehicle.getTenantId(), e);
            throw new RuntimeException("创建车辆失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVehicle(Vehicle vehicle) {
        try {
            Vehicle existVehicle = vehicleMapper.selectById(vehicle.getId());
            if (existVehicle == null || !vehicle.getTenantId().equals(existVehicle.getTenantId())) {
                return false;
            }
            
            vehicle.setUpdateTime(LocalDateTime.now());
            
            int result = vehicleMapper.updateById(vehicle);
            
            log.info("更新车辆成功: vehicleId={}, licensePlate={}, tenantId={}", 
                    vehicle.getId(), vehicle.getLicensePlate(), vehicle.getTenantId());
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("更新车辆异常: vehicleId={}, tenantId={}", vehicle.getId(), vehicle.getTenantId(), e);
            throw new RuntimeException("更新车辆失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteVehicle(Long id, Long tenantId) {
        try {
            Vehicle vehicle = vehicleMapper.selectById(id);
            if (vehicle == null || !tenantId.equals(vehicle.getTenantId())) {
                return false;
            }
            
            // 检查车辆是否有关联的司机
            if (vehicle.getDriverId() != null) {
                throw new RuntimeException("车辆已分配给司机，无法删除");
            }
            
            int result = vehicleMapper.deleteById(id);
            
            log.info("删除车辆成功: vehicleId={}, licensePlate={}, tenantId={}", 
                    id, vehicle.getLicensePlate(), tenantId);
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("删除车辆异常: vehicleId={}, tenantId={}", id, tenantId, e);
            throw new RuntimeException("删除车辆失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteVehicles(List<Long> ids, Long tenantId) {
        try {
            for (Long id : ids) {
                if (!deleteVehicle(id, tenantId)) {
                    throw new RuntimeException("批量删除车辆失败: vehicleId=" + id);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("批量删除车辆异常: tenantId={}", tenantId, e);
            throw new RuntimeException("批量删除车辆失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignToDriver(Long id, Long driverId, Long tenantId) {
        try {
            Vehicle vehicle = vehicleMapper.selectById(id);
            if (vehicle == null || !tenantId.equals(vehicle.getTenantId())) {
                return false;
            }
            
            // 检查车辆状态
            if (!Vehicle.Status.ACTIVE.getValue().equals(vehicle.getStatus())) {
                throw new RuntimeException("车辆状态异常，无法分配");
            }
            
            // 检查车辆是否已分配
            if (vehicle.getDriverId() != null) {
                throw new RuntimeException("车辆已分配给其他司机");
            }
            
            int result = vehicleMapper.assignToDriver(id, driverId, tenantId);
            
            log.info("车辆分配司机成功: vehicleId={}, driverId={}, tenantId={}", id, driverId, tenantId);
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("车辆分配司机异常: vehicleId={}, driverId={}, tenantId={}", id, driverId, tenantId, e);
            throw new RuntimeException("车辆分配司机失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unassignFromDriver(Long id, Long tenantId) {
        try {
            Vehicle vehicle = vehicleMapper.selectById(id);
            if (vehicle == null || !tenantId.equals(vehicle.getTenantId())) {
                return false;
            }
            
            int result = vehicleMapper.assignToDriver(id, null, tenantId);
            
            log.info("车辆取消分配成功: vehicleId={}, tenantId={}", id, tenantId);
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("车辆取消分配异常: vehicleId={}, tenantId={}", id, tenantId, e);
            throw new RuntimeException("车辆取消分配失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchAssignToDriver(List<Long> vehicleIds, Long driverId, Long tenantId) {
        try {
            for (Long vehicleId : vehicleIds) {
                if (!assignToDriver(vehicleId, driverId, tenantId)) {
                    throw new RuntimeException("批量分配车辆失败: vehicleId=" + vehicleId);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("批量分配车辆异常: driverId={}, tenantId={}", driverId, tenantId, e);
            throw new RuntimeException("批量分配车辆失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Integer status, Long tenantId) {
        try {
            Vehicle vehicle = vehicleMapper.selectById(id);
            if (vehicle == null || !tenantId.equals(vehicle.getTenantId())) {
                return false;
            }
            
            int result = vehicleMapper.updateStatus(id, status, tenantId);
            
            log.info("更新车辆状态成功: vehicleId={}, status={}, tenantId={}", id, status, tenantId);
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("更新车辆状态异常: vehicleId={}, status={}, tenantId={}", id, status, tenantId, e);
            throw new RuntimeException("更新车辆状态失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateStatus(List<Long> ids, Integer status, Long tenantId) {
        try {
            for (Long id : ids) {
                if (!updateStatus(id, status, tenantId)) {
                    throw new RuntimeException("批量更新车辆状态失败: vehicleId=" + id);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("批量更新车辆状态异常: tenantId={}", tenantId, e);
            throw new RuntimeException("批量更新车辆状态失败", e);
        }
    }

    @Override
    public String generateVehicleCode(Long tenantId) {
        String datePart = LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"));
        String randomPart = String.format("%04d", new Random().nextInt(10000));
        return VEHICLE_CODE_PREFIX + datePart + randomPart;
    }

    @Override
    public boolean validateVehicleCodeUniqueness(String vehicleCode, Long excludeId, Long tenantId) {
        Vehicle existVehicle = vehicleMapper.selectByVehicleCode(vehicleCode, tenantId);
        return existVehicle == null || (excludeId != null && excludeId.equals(existVehicle.getId()));
    }

    @Override
    public boolean validateLicensePlateUniqueness(String licensePlate, Long excludeId, Long tenantId) {
        Vehicle existVehicle = vehicleMapper.selectByLicensePlate(licensePlate, tenantId);
        return existVehicle == null || (excludeId != null && excludeId.equals(existVehicle.getId()));
    }

    @Override
    public Map<String, Object> getStatistics(Long tenantId) {
        Map<String, Object> statistics = new HashMap<>();
        
        try {
            Long totalCount = vehicleMapper.countByTenantId(tenantId);
            Long activeCount = vehicleMapper.countByStatus(Vehicle.Status.ACTIVE.getValue(), tenantId);
            Long availableCount = vehicleMapper.countAvailableVehicles(tenantId);
            Long assignedCount = vehicleMapper.countAssignedVehicles(tenantId);
            
            statistics.put("totalCount", totalCount);
            statistics.put("activeCount", activeCount);
            statistics.put("inactiveCount", totalCount - activeCount);
            statistics.put("availableCount", availableCount);
            statistics.put("assignedCount", assignedCount);
            statistics.put("unassignedCount", activeCount - assignedCount);
            
            // 按车辆类型统计
            Map<String, Long> typeStatistics = new HashMap<>();
            typeStatistics.put("smallTruck", vehicleMapper.countByVehicleType(Vehicle.VehicleType.SMALL_TRUCK.getValue(), tenantId));
            typeStatistics.put("mediumTruck", vehicleMapper.countByVehicleType(Vehicle.VehicleType.MEDIUM_TRUCK.getValue(), tenantId));
            typeStatistics.put("largeTruck", vehicleMapper.countByVehicleType(Vehicle.VehicleType.LARGE_TRUCK.getValue(), tenantId));
            typeStatistics.put("van", vehicleMapper.countByVehicleType(Vehicle.VehicleType.VAN.getValue(), tenantId));
            typeStatistics.put("refrigeratedTruck", vehicleMapper.countByVehicleType(Vehicle.VehicleType.REFRIGERATED_TRUCK.getValue(), tenantId));
            
            statistics.put("typeStatistics", typeStatistics);
            
        } catch (Exception e) {
            log.error("获取车辆统计信息异常: tenantId={}", tenantId, e);
        }
        
        return statistics;
    }

    @Override
    public List<Map<String, Object>> exportVehicles(String vehicleCode, String licensePlate, Long driverId,
                                                   Integer status, Integer vehicleType, LocalDateTime startTime, LocalDateTime endTime, Long tenantId) {
        try {
            return vehicleMapper.exportVehicles(vehicleCode, licensePlate, driverId, status, vehicleType, startTime, endTime, tenantId);
        } catch (Exception e) {
            log.error("导出车辆信息异常: tenantId={}", tenantId, e);
            throw new RuntimeException("导出车辆信息失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> importVehicles(List<Map<String, Object>> vehicleList, Long tenantId) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        StringBuilder errorMsg = new StringBuilder();
        
        try {
            for (int i = 0; i < vehicleList.size(); i++) {
                try {
                    Map<String, Object> vehicleData = vehicleList.get(i);
                    
                    Vehicle vehicle = new Vehicle();
                    vehicle.setLicensePlate((String) vehicleData.get("licensePlate"));
                    vehicle.setBrand((String) vehicleData.get("brand"));
                    vehicle.setModel((String) vehicleData.get("model"));
                    vehicle.setVehicleType(Integer.valueOf(vehicleData.get("vehicleType").toString()));
                    vehicle.setLoadCapacity(Double.valueOf(vehicleData.get("loadCapacity").toString()));
                    vehicle.setVolumeCapacity(Double.valueOf(vehicleData.get("volumeCapacity").toString()));
                    vehicle.setTenantId(tenantId);
                    
                    // 验证车牌号唯一性
                    if (!validateLicensePlateUniqueness(vehicle.getLicensePlate(), null, tenantId)) {
                        failCount++;
                        errorMsg.append("第").append(i + 1).append("行：车牌号已存在；");
                        continue;
                    }
                    
                    if (createVehicle(vehicle)) {
                        successCount++;
                    } else {
                        failCount++;
                        errorMsg.append("第").append(i + 1).append("行：创建失败；");
                    }
                    
                } catch (Exception e) {
                    failCount++;
                    errorMsg.append("第").append(i + 1).append("行：").append(e.getMessage()).append("；");
                }
            }
            
            result.put("success", true);
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("errorMsg", errorMsg.toString());
            
            log.info("导入车辆完成: 成功{}条，失败{}条，tenantId={}", successCount, failCount, tenantId);
            
        } catch (Exception e) {
            log.error("导入车辆异常: tenantId={}", tenantId, e);
            result.put("success", false);
            result.put("message", "导入车辆失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getMaintenanceReminder(Long tenantId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取需要保养的车辆（根据里程数或时间）
            List<Vehicle> maintenanceVehicles = vehicleMapper.selectMaintenanceVehicles(tenantId);
            
            // 获取保险即将到期的车辆
            List<Vehicle> insuranceExpiringVehicles = vehicleMapper.selectInsuranceExpiringVehicles(tenantId);
            
            // 获取年检即将到期的车辆
            List<Vehicle> inspectionExpiringVehicles = vehicleMapper.selectInspectionExpiringVehicles(tenantId);
            
            result.put("maintenanceVehicles", maintenanceVehicles);
            result.put("insuranceExpiringVehicles", insuranceExpiringVehicles);
            result.put("inspectionExpiringVehicles", inspectionExpiringVehicles);
            
            result.put("maintenanceCount", maintenanceVehicles.size());
            result.put("insuranceExpiringCount", insuranceExpiringVehicles.size());
            result.put("inspectionExpiringCount", inspectionExpiringVehicles.size());
            
        } catch (Exception e) {
            log.error("获取车辆维护提醒异常: tenantId={}", tenantId, e);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMileage(Long id, Double mileage, Long tenantId) {
        try {
            Vehicle vehicle = vehicleMapper.selectById(id);
            if (vehicle == null || !tenantId.equals(vehicle.getTenantId())) {
                return false;
            }
            
            int result = vehicleMapper.updateMileage(id, mileage, tenantId);
            
            log.info("更新车辆里程成功: vehicleId={}, mileage={}, tenantId={}", id, mileage, tenantId);
            
            return result > 0;
            
        } catch (Exception e) {
            log.error("更新车辆里程异常: vehicleId={}, mileage={}, tenantId={}", id, mileage, tenantId, e);
            return false;
        }
    }

    @Override
    public List<Vehicle> getNearbyVehicles(Double longitude, Double latitude, Double radius, Long tenantId) {
        try {
            return vehicleMapper.selectNearbyVehicles(longitude, latitude, radius, tenantId);
        } catch (Exception e) {
            log.error("查询附近车辆异常: longitude={}, latitude={}, radius={}, tenantId={}", 
                     longitude, latitude, radius, tenantId, e);
            return List.of();
        }
    }

    @Override
    public Map<String, Object> getVehicleUtilizationStatistics(String startDate, String endDate, Long tenantId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取车辆利用率统计
            List<Map<String, Object>> utilizationStats = vehicleMapper.selectVehicleUtilizationStatistics(startDate, endDate, tenantId);
            
            result.put("utilizationStats", utilizationStats);
            result.put("totalVehicles", vehicleMapper.countByTenantId(tenantId));
            
            // 计算平均利用率
            double avgUtilization = utilizationStats.stream()
                    .mapToDouble(stat -> Double.parseDouble(stat.get("utilizationRate").toString()))
                    .average()
                    .orElse(0.0);
            
            result.put("avgUtilization", avgUtilization);
            
        } catch (Exception e) {
            log.error("获取车辆利用率统计异常: startDate={}, endDate={}, tenantId={}", 
                     startDate, endDate, tenantId, e);
        }
        
        return result;
    }
}